package com.rickpan.service;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.rickpan.dto.siliconflow.SiliconFlowRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.client.ResponseExtractor;
import org.springframework.web.client.RestTemplate;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.function.Consumer;

/**
 * 硅基流动AI API客户端
 */
@Component
public class SiliconFlowClient {

    private static final Logger log = LoggerFactory.getLogger(SiliconFlowClient.class);
    private static final String SILICONFLOW_API_URL = "https://api.siliconflow.cn/v1/chat/completions";
    
    @Autowired
    private RestTemplate restTemplate;
    
    @Autowired
    private ObjectMapper objectMapper;

    /**
     * 发送请求到硅基流动AI（非流式）
     * @param apiKey API密钥
     * @param request 请求对象
     * @return 响应内容
     */
    public String sendRequest(String apiKey, SiliconFlowRequest request) {
        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", "Bearer " + apiKey);
        headers.set("Content-Type", "application/json");

        try {
            HttpEntity<SiliconFlowRequest> entity = new HttpEntity<>(request, headers);
            ResponseEntity<String> response = restTemplate.exchange(
                    SILICONFLOW_API_URL, HttpMethod.POST, entity, String.class);

            if (response.getStatusCode().is2xxSuccessful()) {
                return parseResponse(response.getBody());
            } else {
                throw new RuntimeException("硅基流动 API调用失败: " + response.getStatusCode());
            }
        } catch (Exception e) {
            log.error("Error in SiliconFlow request: {}", e.getMessage(), e);
            
            // 特殊处理429错误（限额超出）
            if (e.getMessage() != null && e.getMessage().contains("429")) {
                throw new RuntimeException("API调用限额已用完，请稍后重试", e);
            }
            
            throw new RuntimeException("硅基流动 API调用失败: " + e.getMessage(), e);
        }
    }

    /**
     * 测试API Key是否有效
     * @param apiKey API密钥
     * @return 是否有效
     */
    public boolean testApiKey(String apiKey) {
        try {
            // 创建简单的测试请求
            SiliconFlowRequest testRequest = SiliconFlowRequest.builder()
                    .model("THUDM/GLM-4.1V-9B-Thinking")
                    .temperature(0.8)
                    .topP(0.8)
                    .stream(false)
                    .addMessage("user", "Hello")
                    .build();

            HttpHeaders headers = new HttpHeaders();
            headers.set("Authorization", "Bearer " + apiKey);
            headers.set("Content-Type", "application/json");

            HttpEntity<SiliconFlowRequest> entity = new HttpEntity<>(testRequest, headers);
            ResponseEntity<String> response = restTemplate.exchange(
                    SILICONFLOW_API_URL, HttpMethod.POST, entity, String.class);

            return response.getStatusCode().is2xxSuccessful();
        } catch (Exception e) {
            log.warn("SiliconFlow API Key test failed: {}", e.getMessage());
            return false;
        }
    }

    /**
     * 发送流式请求到硅基流动AI
     * @param apiKey API密钥
     * @param request 请求对象（会自动设置stream=true）
     * @param outputStream 输出流，用于写入SSE数据
     */
    public void sendStreamRequest(String apiKey, SiliconFlowRequest request, OutputStream outputStream) throws IOException {
        // 确保请求是流式的
        request.setStream(true);

        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", "Bearer " + apiKey);
        headers.set("Content-Type", "application/json");
        headers.set("Accept", "text/event-stream");
        headers.set("Cache-Control", "no-cache");

        try {
            HttpEntity<SiliconFlowRequest> entity = new HttpEntity<>(request, headers);

            // 使用ResponseExtractor处理流式响应
            restTemplate.execute(SILICONFLOW_API_URL, HttpMethod.POST,
                requestCallback -> {
                    requestCallback.getHeaders().putAll(headers);
                    try {
                        objectMapper.writeValue(requestCallback.getBody(), request);
                    } catch (IOException e) {
                        throw new RuntimeException("Failed to write request body", e);
                    }
                },
                new StreamResponseExtractor(outputStream)
            );

        } catch (Exception e) {
            log.error("Error in SiliconFlow stream request: {}", e.getMessage(), e);

            // 根据异常类型提供更友好的错误信息
            String userFriendlyMessage = getUserFriendlyErrorMessage(e);

            try {
                // 发送错误信息到客户端
                String errorMessage = "data: {\"error\":\"" + userFriendlyMessage + "\"}\n\n";
                outputStream.write(errorMessage.getBytes(StandardCharsets.UTF_8));
                outputStream.flush();

                // 发送结束标记
                outputStream.write("data: [DONE]\n\n".getBytes(StandardCharsets.UTF_8));
                outputStream.flush();
            } catch (IOException ioException) {
                log.warn("Failed to send error message to client: {}", ioException.getMessage());
            }

            throw new RuntimeException("硅基流动流式API调用失败: " + e.getMessage(), e);
        }
    }

    /**
     * 流式响应提取器
     */
    private class StreamResponseExtractor implements ResponseExtractor<Void> {
        private final OutputStream outputStream;

        public StreamResponseExtractor(OutputStream outputStream) {
            this.outputStream = outputStream;
        }

        @Override
        public Void extractData(ClientHttpResponse response) throws IOException {
            if (!response.getStatusCode().is2xxSuccessful()) {
                String errorMessage = getHttpErrorMessage(response.getStatusCode().value());
                String sseError = "data: {\"error\":\"" + errorMessage + "\"}\n\n";
                outputStream.write(sseError.getBytes(StandardCharsets.UTF_8));
                outputStream.flush();

                // 发送结束标记
                outputStream.write("data: [DONE]\n\n".getBytes(StandardCharsets.UTF_8));
                outputStream.flush();
                return null;
            }

            try (BufferedReader reader = new BufferedReader(
                    new InputStreamReader(response.getBody(), StandardCharsets.UTF_8))) {

                String line;
                while ((line = reader.readLine()) != null) {
                    // 处理SSE格式的数据行
                    if (line.startsWith("data: ")) {
                        String jsonData = line.substring(6).trim();

                        // 检查是否是结束标记
                        if ("[DONE]".equals(jsonData)) {
                            outputStream.write("data: [DONE]\n\n".getBytes(StandardCharsets.UTF_8));
                            outputStream.flush();
                            break;
                        }

                        // 解析JSON并提取content
                        try {
                            if (!jsonData.isEmpty() && jsonData.startsWith("{")) {
                                JsonNode jsonNode = objectMapper.readTree(jsonData);

                                // 检查是否有错误信息
                                if (jsonNode.has("error")) {
                                    JsonNode error = jsonNode.get("error");
                                    String errorMsg = error.has("message") ? error.get("message").asText() : "未知错误";
                                    log.warn("SiliconFlow API returned error: {}", errorMsg);

                                    String sseError = "data: {\"error\":\"" + errorMsg + "\"}\n\n";
                                    outputStream.write(sseError.getBytes(StandardCharsets.UTF_8));
                                    outputStream.flush();

                                    // 发送结束标记并退出
                                    outputStream.write("data: [DONE]\n\n".getBytes(StandardCharsets.UTF_8));
                                    outputStream.flush();
                                    break;
                                }

                                JsonNode choices = jsonNode.get("choices");
                                if (choices != null && choices.isArray() && choices.size() > 0) {
                                    JsonNode delta = choices.get(0).get("delta");
                                    if (delta != null) {
                                        // 处理推理内容 (reasoning_content)
                                        if (delta.has("reasoning_content")) {
                                            JsonNode reasoningNode = delta.get("reasoning_content");
                                            if (reasoningNode != null && !reasoningNode.isNull()) {
                                                String reasoning = reasoningNode.asText();
                                                if (reasoning != null && !reasoning.isEmpty()) {
                                                    // 发送推理内容，使用JSON格式标识类型
                                                    String reasoningData = "{\"type\":\"reasoning\",\"content\":\"" +
                                                        reasoning.replace("\"", "\\\"").replace("\n", "\\n").replace("\r", "\\r") + "\"}";
                                                    String sseData = "data: " + reasoningData + "\n\n";
                                                    outputStream.write(sseData.getBytes(StandardCharsets.UTF_8));
                                                    outputStream.flush();
                                                }
                                            }
                                        }

                                        // 处理回答内容 (content)
                                        if (delta.has("content")) {
                                            JsonNode contentNode = delta.get("content");
                                            // 检查content节点不为null且不是null值
                                            if (contentNode != null && !contentNode.isNull()) {
                                                String content = contentNode.asText();
                                                if (content != null && !content.isEmpty()) {
                                                    // 发送回答内容，使用JSON格式标识类型
                                                    String contentData = "{\"type\":\"content\",\"content\":\"" +
                                                        content.replace("\"", "\\\"").replace("\n", "\\n").replace("\r", "\\r") + "\"}";
                                                    String sseData = "data: " + contentData + "\n\n";
                                                    outputStream.write(sseData.getBytes(StandardCharsets.UTF_8));
                                                    outputStream.flush();
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        } catch (Exception e) {
                            log.warn("Failed to parse streaming JSON: {}, error: {}", jsonData, e.getMessage());
                            // 继续处理下一行，不中断流式传输
                        }
                    }
                }

            } catch (IOException e) {
                log.warn("Client disconnected during streaming: {}", e.getMessage());
                // 客户端断开连接，正常情况
            }

            return null;
        }
    }

    /**
     * 解析硅基流动AI响应，提取消息内容
     * @param responseBody 响应体
     * @return 消息内容
     */
    private String parseResponse(String responseBody) {
        try {
            JsonNode jsonNode = objectMapper.readTree(responseBody);
            JsonNode choices = jsonNode.get("choices");
            if (choices != null && choices.isArray() && choices.size() > 0) {
                JsonNode message = choices.get(0).get("message");
                if (message != null && message.has("content")) {
                    return message.get("content").asText();
                }
            }
            return "解析响应失败";
        } catch (Exception e) {
            log.error("Error parsing SiliconFlow response: {}", e.getMessage());
            return "解析响应失败: " + e.getMessage();
        }
    }

    /**
     * 根据异常类型返回用户友好的错误信息
     * @param e 异常对象
     * @return 用户友好的错误信息
     */
    private String getUserFriendlyErrorMessage(Exception e) {
        String message = e.getMessage();

        // 网络连接错误
        if (message != null && (message.contains("Connection") || message.contains("timeout") ||
                               message.contains("UnknownHost") || message.contains("ConnectException"))) {
            return "网络连接失败，请检查网络连接";
        }

        // API限额错误
        if (message != null && (message.contains("429") || message.contains("rate limit") ||
                               message.contains("quota") || message.contains("limit"))) {
            return "API调用限额已用完，请稍后重试";
        }

        // 认证错误
        if (message != null && (message.contains("401") || message.contains("Unauthorized") ||
                               message.contains("Invalid API key"))) {
            return "API Key无效，请检查配置";
        }

        // 服务器错误
        if (message != null && (message.contains("500") || message.contains("502") ||
                               message.contains("503") || message.contains("504"))) {
            return "AI服务暂时不可用，请稍后重试";
        }

        // JSON解析错误
        if (e instanceof com.fasterxml.jackson.core.JsonProcessingException) {
            return "响应数据格式错误";
        }

        // 默认错误信息
        return "AI服务调用失败，请稍后重试";
    }

    /**
     * 根据HTTP状态码返回用户友好的错误信息
     * @param statusCode HTTP状态码
     * @return 用户友好的错误信息
     */
    private String getHttpErrorMessage(int statusCode) {
        switch (statusCode) {
            case 400:
                return "请求参数错误";
            case 401:
                return "API Key无效，请检查配置";
            case 403:
                return "访问被拒绝，请检查权限";
            case 404:
                return "API接口不存在";
            case 429:
                return "API调用限额已用完，请稍后重试";
            case 500:
                return "AI服务内部错误";
            case 502:
                return "AI服务网关错误";
            case 503:
                return "AI服务暂时不可用";
            case 504:
                return "AI服务响应超时";
            default:
                return "AI服务调用失败 (HTTP " + statusCode + ")";
        }
    }
}
